package com.abe.libfitness.base;

import android.os.Bundle;
import android.util.Log;

import com.abe.libcore.base.permission.PermissionUtils;
import com.abe.libfitness.entity.ComReceiveDataBean;
import com.abe.libfitness.entity.SerialPortCommand;
import com.abe.libfitness.utils.ConstantFitness;
import com.abe.libfitness.utils.DataCovertUtil;
import com.abe.libfitness.utils.ProtocolV3Utils;
import com.abe.libquick.utils.quick.EmptyUtils;
import com.google.gson.Gson;
import com.yanzhenjie.permission.runtime.Permission;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Locale;

import android_serialport_api.SerialPort;
import butterknife.ButterKnife;

public abstract class BaseComActivity extends BaseActivity {
    protected ComApplication mComApplication = null;
    //日志工具
    protected StringBuilder builder;
    //命令失败重发次数
    protected int resendCount = 5;
    //当前发送命令
    protected SerialPortCommand currentCommand;
    //是否当前有命令正在执行
    protected boolean isCommandRun;
    //自动重发线程
    protected autoResendThread resendThread;
    //读数据线程
    protected ReadThread mReadThread = null;

    protected boolean mReadEndFlag = false;
    private SerialPort mSerialPort = null;
    private OutputStream mOutputStream = null;
    private InputStream mInputStream = null;

    protected abstract void onDataReceived(ComReceiveDataBean ComRecData);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        builder = new StringBuilder();
        builder.append("------------------------------------------------------------------------\n");
        super.onCreate(savedInstanceState);
        ButterKnife.bind(this);
        openSerialPort();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mReadEndFlag = false;
        mReadThread = new ReadThread();
        mReadThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        closeThread();
    }

    protected void openSerialPort() {
        try {
            mComApplication = (ComApplication) getApplication();
            mSerialPort = mComApplication.getSerialPortInstance();
            if (mSerialPort != null) {
                mOutputStream = mSerialPort.getOutputStream();
                mInputStream = mSerialPort.getInputStream();
            }
        } catch (SecurityException e) {
            Log.d(TAG, "initial:" + e.toString());
        }
    }

    protected void closeSerialPort() {
        try {
            if (mOutputStream != null) {
                mOutputStream.close();
                mOutputStream = null;
            }
            if (mInputStream != null) {
                mInputStream.close();
                mInputStream = null;
            }
            if (mSerialPort != null) {
                mSerialPort.close();
                mSerialPort = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void send(byte[] bOutArray) {
        builderW(ConstantFitness.LOG_FLAG_SEND);
        try {
            if (mOutputStream != null) {
                mOutputStream.write(bOutArray);
                mOutputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //发送单条命令
    protected void sendCommand(SerialPortCommand command) {
        sendCommand(command, ProtocolV3Utils.SerialPortDefault);
    }

    /**
     * @param command   命令
     * @param delayTime 单位为10ms
     */
    protected void sendCommand(SerialPortCommand command, int delayTime) {
        if (resendThread != null) {
            resendThread.stopSend();
            resendThread = null;
        }
        this.currentCommand = command;
        resendThread = new autoResendThread(command, delayTime);
        new Thread(resendThread).start();
    }

    protected void closeReadThread() {
        mReadEndFlag = true;
        try {
            if (mReadThread != null && mReadThread.isAlive()) {
                mReadThread.interrupt();
                mReadThread = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void closeSendThread() {
        try {
            if (resendThread != null) {
                resendThread.stopSend();
                resendThread = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void closeThread() {
        closeReadThread();
        closeSendThread();
    }

    protected void verification(final ComReceiveDataBean ComRecData) {
        if (!isAlive) return;
        boolean result;
        result = ProtocolV3Utils.isReceiveData(ComRecData.bRec);
        if (!result) return;
        result = ComRecData.verification();
        if (result) {
            builder.append("收到返回值1：").append(new Gson().toJson(ComRecData.bRec)).append("\n");
            builderW(ConstantFitness.LOG_FLAG_DATA);
            //wBase("收到:" + json(ComRecData.bRec));
            onDataReceived(ComRecData);
        } else {
            builder.append("校验失败\n");
            builderW(ConstantFitness.LOG_FLAG_DATA);
        }
    }

    protected void builderW(String tag) {
        if (EmptyUtils.isNotEmpty(tag)) return;
        PermissionUtils.INSTANCE.request(this, () -> {
            builder.append(String.format(Locale.CHINA, "%s------------------------------------------------------------------------\n", tag));
            ProtocolV3Utils.saveLocalDailyLog(builder.toString());
            builder.delete(0, builder.length());
        }, Permission.Group.STORAGE);
    }

    ///设置命令发送后，等待数据接收，并判断是否接收完毕
    //应该接收到的数据判断
    //0.接收完毕 1 未收到数据
    private int isRxFinish() throws IOException {
        int rxCnt = 0;
        MyTimer mt = new MyTimer();   //用于判断是否接收完毕的定时器
        MyTimer timeout = new MyTimer();//用于判断是否超时的定时器
        timeout.Start();
        mt.Start();
        while (true) {
            switch (mInputStream.available())//判断接收的字节数
            {
                case 0://为0 没有收到数据，超过设定值后，返回接收超时
                    if (timeout.GetTimeCountMS() > 1000) {
                        return 1;
                    }
                    break;
                default://个数不为0，收到数据，10ms没有接到新数据，接收完成
                    if (rxCnt != mInputStream.available()) {
                        mt.reStart();
                        rxCnt = mInputStream.available();
                    } else {
                        if (mt.GetTimeCountMS() >= 3) {
                            return 0;
                        }
                    }
                    break;
            }
        }
    }

    protected class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            Log.d(TAG, "--------------->read start:");
            while (!isInterrupted() && !mReadEndFlag) {
                try {
                    if (mInputStream == null) {
                        return;
                    }
                    if (isRxFinish() == 0) {
                        synchronized (this) {
                            byte[] buffer = new byte[60];
                            int size = mInputStream.read(buffer);
                            if (size > 0) {
                                ComReceiveDataBean comReceiveDataBean = new ComReceiveDataBean(buffer, size);
                                Log.d(TAG, "--------------->ReadThread readData:"
                                        + DataCovertUtil.ByteArrToHex(comReceiveDataBean.bRec));
                                verification(comReceiveDataBean);// ui
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d(TAG, "ReadThread2:" + e.toString());
                    return;
                }
            }
            Log.d(TAG, "--------------->read end");
        }
    }

    class MyTimer {
        Date startDate = new Date();

        void Start() {
            startDate = new Date();
        }

        void reStart() {
            startDate = new Date();
        }

        long GetTimeCountMS() {
            return new Date().getTime() - startDate.getTime();
        }
    }

    //命令自动重发线程
    public class autoResendThread implements Runnable {

        //线程控制
        private boolean mSendEndFlag;
        //当前命令执行次数
        private int currentSendCount;
        //当前命令
        private SerialPortCommand sendCommand;
        //命令间隔时间
        private int delay;

        public autoResendThread(SerialPortCommand sendCommand, int delay) {
            builder.append("启动命令发送线程").append("\n");
            builder.append(sendCommand.toString()).append("\n");
            this.mSendEndFlag = true;
            currentSendCount = 0;
            this.sendCommand = sendCommand;
            this.delay = delay;
        }

        @Override
        public void run() {
            try {
                int timeOutCommand = 0;
                builder.append("发送计数：");
                while (mSendEndFlag && currentSendCount < resendCount && sendCommand != null) {
                    if (isCommandRun) {
                        //当前命令正在执行
                        timeOutCommand++;
                    } else {
                        timeOutCommand = 0;
                    }
                    //自动解锁命令发送，防止一直未收到回复
                    if (timeOutCommand >= delay) {
                        timeOutCommand = 0;
                        isCommandRun = false;
                    }
                    if (!isCommandRun && mSendEndFlag) {
                        isCommandRun = true;
                        currentSendCount++;
                        builder.append(currentSendCount).append("---");
                        send(sendCommand.command);
                    }
                    if (mSendEndFlag) {
                        Thread.sleep(10);
                    }
                }
                if (currentSendCount == resendCount) {
                    //通讯故障
                    toast("通讯故障");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //线程停止外部接口
        public synchronized void stopSend() {
            mSendEndFlag = false;
            currentSendCount = 0;
        }
    }
}